# -*-coding:utf-8-*-
'''
    > type definition       >
    > declaration           >
    > e-data definition     >
    > function definition   >
    <<<<<<<<<<<<<<<<<<<<<<<<<

    class structure:
        c_code_reader  ---->    {
        {                           type_definition_analyzer,
            base function           declaration_anlyzer,
            module info             e_data_definition_anlyzer,
        }                           function_analyzer
                                } ----> module_analyzer

'''
import time
import os
from c_code_base_analyzer import print_comment, eat_units
from type_definition_analyzer import type_definition_analyzer
from declaration_analzyer import declaration_anlyzer
from e_data_definition_anlyzer import e_data_definition_anlyzer
from function_analyzer import function_analyzer


class module_analyzer(type_definition_analyzer, declaration_anlyzer,
                      e_data_definition_anlyzer, function_analyzer):
    def __init__(self, name, content):
        self.module_info.module_name = name
        self.module_dir = os.path.dirname(name)
        self.current_path = name
        self.analyzing_dir = os.path.dirname(name)
        self.prev_dir = os.path.dirname(name)
        self.content = content
        self.eof_mark = "====" + str(time.time()) + "===="
        self.handlers = [
            self.macro_switch, self.include_path_analyze, self.define_analyze,
            self.function_end_judge, self.assemble_line,
            self.type_definition_analyze, self.declaration_anlyze,
            self.e_data_definition_anlyze, self.function_analyze
        ]
        self.type_definition_init()

    def special_key_word_filter(self, line_left):
        filter_words = [
            '__attribute__((__packed__))'
        ]
        for word in filter_words:
            line_left = line_left.replace(word,'')
        return line_left

    def start(self):
        print_comment("start analyze")
        i = -1
        self.current_handler = self.comment_jumpper
        path_tmp_list = []
        while i < len(self.content) - 1 and self.crashed is False:
            i += 1
            '''
            to update and backup the path to analyze
            '''
            cur_path, result = eat_units(self.content[i],
                                         "//include file expand start:")
            if result is True:
                path_tmp_list.append(self.current_path)
                self.current_path = cur_path
            '''
            to restore the path to analyze
            '''
            cur_path, result = eat_units(self.content[i],
                                         "//include file expand end:")
            if result is True:
                self.current_path = path_tmp_list.pop()
            '''
            judge if is end in include file
            '''
            is_end_in_expand_file = (self.content[i] == self.eof_mark)
            '''
            expand the include file
            '''
            self.include_file_expand(i, is_end_in_expand_file)
            '''
            to judge if is in end of include file.
            '''
            if is_end_in_expand_file:
                continue
            print_comment("line " + str(i) + ":" + self.content[i].rstrip())
            self.content[i] = self.comment_jumpper(self.content[i])

            if self.is_in_function and self.content[i].strip()!= '' and self.content[i].strip()[0] != '#' and self.compile_flag is True:
                self.function_tmp.func_content.append(self.content[i])

            self.defined_symbol_expand(i)
            '''
            multi line macro solution.
            '''
            if self.macro_call_incomplete is True:
                self.content[i] += self.content[i + 1]
                self.content.remove(self.content[i + 1])
                i -= 1
                continue

            line_left = self.special_key_word_filter(self.content[i])
            print_comment("to anlyze:" + line_left + "\n")
            '''
            multi-line handler solution: call last handler we analyzed.
            '''
            if (self.current_handler is not None):
                line_left = self.current_handler(line_left)

            while (line_left.strip() != ""):
                self.unit_handled = False
                for handler in self.handlers:
                    self.current_handler = handler
                    print_comment("(L1)handler:" + str(handler))
                    line_left = self.current_handler(line_left)
                    if (line_left == ""):
                        if self.unit_handled is True:
                            self.current_handler = self.comment_jumpper
                        break
                if line_left != "" and self.unit_handled is False:
                    print_comment("crashed! with:" + line_left)
                    self.crashed = True
                    break
        return self.module_info
